home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
CPSTRING.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-08
|
8KB
|
277 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: cpstring.c
// Title: Data Compression Library
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
//
// This module contains a string encoding function. It uses a combination of
// nybble encoding and word caching to compress a string.
//
// The code in this module should be written entirely in C.
// Do not use any C++ constructs.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
// SCO UNIX.
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
// SCO UNIX cc
//
//----------------------------------------------------------------------------
#include <cp.h>
//----------------------------------------------------------------------------
// Description: Decode a string buffer
// Parameters: pv Pointer to word cache.
// pbDecode Pointer to buffer to decode.
// pcDecode Pointer to receive number of bytes decoded.
// pch Buffer to place decoded text into.
// Null terminator is added to buffer.
// Buffer is assumed to be of sufficient size.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E StringDecode(PVOID pv, PBYTE pbDecode, PSIZET pcDecode, PCHAR pch)
{
SIZET cNybble;
SIZET cDecode = 0;
BOOL fFirst = TRUE;
PCHAR pchSave = pch;
Assert(pv && pbDecode && pcDecode && pch);
*pch = '\0'; // Start with an empty string
while (*pbDecode)
{
if (!fFirst) // Insert spaces between words
{
*pch++ = ' ';
*pch = '\0';
}
if ((*pbDecode) & 0x80) // A cached word
{
strcpy(pch, WordDecode(pv, *pbDecode));
cDecode++;
pbDecode++;
} // Final word
else if (((*pbDecode) & 0x40)
&& *pbDecode != 0x7F)
{
pbDecode[0] &= ~0x40;
NybbleDecode(pbDecode, &cNybble, pch);
pbDecode[0] |= 0x40;
WordEncode(pv, pch, TRUE); // Update cache
cDecode += cNybble;
*pcDecode = cDecode;
if (pchSave[0] && pchSave[1]) // Update cache w/ whole string
WordEncode(pv, pchSave, TRUE);
return TRUE;
}
else // A nybble encoded sequence
{
NybbleDecode(pbDecode, &cNybble, pch);
WordEncode(pv, pch, TRUE); // Update cache
cDecode += cNybble;
pbDecode += cNybble;
}
pch = strchr( pch, '\0');
fFirst = FALSE;
}
*pcDecode = cDecode + 1; // + 1 for final 0 byte
if (pchSave[0] && pchSave[1]) // Update cache w/ whole string
WordEncode(pv, pchSave, TRUE);
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Encode a string
// Parameters: pbEncode Pointer to buffer to encode into.
// pcEncode Pointer to variable to recieve size of
// encoded text.
// Buffer must be of sufficient size.
// Maximum size is strlen(pcsz)+2.
// pcsz Buffer to read text from.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E StringEncode(PVOID pv, PBYTE pbEncode, PSIZET pcEncode, PCSZ pcsz)
{
SIZET cEncode = 0;
PSZ psz = (PSZ)pcsz;
PSZ pszSpace;
CHAR ch;
BYTE bVal;
if (!psz[0]) // Special case of zero length
{ // string!
*pbEncode = 0;
*pcEncode = 1;
return TRUE;
}
bVal = WordEncode(pv, psz, FALSE); // Encode entire string
if (bVal) // Entire string already cached!
{
*pbEncode++ = bVal;
cEncode++;
*pbEncode = 0; // Final word is cached, add
cEncode++; // trailing null
psz = strchr(psz, '\0'); // Move to end of string
}
while (psz[0])
{
pszSpace = psz; // Skip leading spaces
while (pszSpace[0] && pszSpace[0] == ' ')
pszSpace++;
// Skip to end of word
while (pszSpace[0] && pszSpace[0] != ' ')
pszSpace++;
// Include multiple spaces
while (pszSpace[0] && (pszSpace[1] == ' ' || pszSpace[1] == '\0'))
pszSpace++;
ch = *pszSpace; // Terminate word
*pszSpace = '\0';
Assert(strlen(psz) < 63); // Word limited to 62 characters!
bVal = WordEncode(pv, psz, TRUE);// Encode word
if (bVal) // Word already cached!
{
*pbEncode++ = bVal;
cEncode++;
if (!ch) // Final word is cached, add
{ // trailing null
*pbEncode = 0;
cEncode++;
}
}
else // Encode as nybble stream
{
SIZET cNybble;
NybbleEncode(pbEncode, &cNybble, psz);
cEncode += cNybble;
if (!ch)
{
if (*pbEncode == 0x7F) // Final word is uncompressed
{ // ascii.
pbEncode += cNybble;
*pbEncode = 0;
cEncode++;
}
else
pbEncode[0] |= 0x40;
}
else
pbEncode += cNybble;
}
*pszSpace = ch; // Replace space character
psz = *pszSpace ? pszSpace + 1: pszSpace;
}
*pcEncode = cEncode; // Return length of encoded string
if (pcsz[0] && pcsz[1]) // Don't encode trivial strings
WordEncode(pv, pcsz, TRUE); // Update cache w/ whole string
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Run standard test suite
// Parameters: sTest Test to run.
// 0 Run all default tests (except).
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
#if COMPILE_TEST
BOOL FN StringTest(SHORT sTest)
{
static CHAR szBuf[80];
static BYTE bBuf[1024];
static PSZ apsz[] =
{
"5TH & L ST", // Ampersand
"", // Empty
" ", // Single space
" ", // Only spaces
" ",
" ",
"EEEE EEEE EEEE EEEE", // Single spaces
"SEE THE BROWN FOX JUMP", // Two identical string
"SEE THE BROWN FOX JUMP",
"SEE THE BROWN FOX ", // A partial match
"THIS IS A TEST OF THE TEST OF A THIS AND A WORD ",
" WORD WORD WORD WORD WORD ", // Multiple spaces
"E", // Should take only 2 bytes
"E", // Single char
"EAOIUSTRLNDMCPH", // All nybble
"FBWYKGVJXQZ-/#&", // All byte
"1234567890", // 2 Byte
"EF1B2AB2OWW3IIY4UK5SG6TV7", // A mix
NULL
};
PVOID pv;
SIZET i;
SIZET cEncode = 0, cDecode = 0;
NOTUSED(sTest);
pv = StringCreate(512, CP_WORD_VERIFY);
if (pv == FALSE)
return FALSE;
for (i = 0; apsz[i]; ++i) // Encode the strings
{
SIZET cString;
StringEncode(pv, bBuf + cEncode, &cString, apsz[i]);
cEncode += cString;
}
StringReset(pv);
for (i = 0; apsz[i]; ++i) // Encode the strings
{
SIZET cString;
StringDecode(pv, bBuf + cDecode, &cString, szBuf);
cDecode += cString;
Output(" Input: (%3d) %s\n", strlen(apsz[i])+1, apsz[i]);
Output("Output: (%3d) %s\n", strlen(szBuf)+1, szBuf);
Output(" Bytes: %3d\n", cString);
if (strcmp(apsz[i], szBuf) != 0)
{
StringDestroy(pv);
return FALSE;
}
}
if (cEncode != cDecode)
{
StringDestroy(pv);
return FALSE;
}
StringDestroy(pv);
return TRUE;
}
#endif
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------